unit uMainFrm;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs,

  GlScene, GlObjects, GlCadencer, GLWin32Viewer, GLRenderContextInfo, GlWindowsFont, GlHudObjects,
  GlMaterial,
  VectorGeometry,
  uTweener;
const
  MatNames: array [1..6] of String = ('compass', 'mail', 'notes', 'store', 'video', 'messages');
type
  TItem = class
    fMainHud: TGlHudSprite;
    fTextHud: TGlHudText;
    fBottomText: String;
    fPosition: TVector;
    fY: Single;
    fSelected: Boolean;
    fWidthArea: Single;
  end;

  TfrmMain = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormActivate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    {Main Objects}
    fGlScene: TGlScene;
    fCadencer: TGLCadencer;
    fViewer: TGLSceneViewer;
    fCamera: TGlCamera;
    fMainDummy: TGlDummyCube;
    fFpsTimer: Single;
    fMatLib: TGlMaterialLibrary;

    {Text Objects}
    fWinFont: TGLWindowsBitmapFont;
    fHudText: TGLHUDText;
    fBack: TGlHudSprite;

    {Tween-objects}
    fTweener: TTweener;

    fMenuItems: TList;
    fTextBar: TGlHudSprite;
    fTextBarX: Single;
    fMenuText: TGlHudText;
    fBottomText: TGlHudText;
    fBottomTextX: Single;

    MousePressed: Boolean;
  protected
    Function AddItem(aMaterial: String; aText: String; aPosX, aPosY, aWidthArea: Single; aBottomText: String): TItem;
    Function GetItem(aIndex: integer): TItem;
    Function UpdateSelection(x, y: Integer): integer;
  public
    Procedure InitFontAndSprites;
    Procedure InitMaterials;
    Procedure InitTweener;
    Procedure SetPositions;
    Procedure OnCadencerProgress(Sender : TObject; const deltaTime, newTime : Double);
  end;

var
  frmMain: TfrmMain;

implementation
uses
  glKeyboard,
  GLCrossPlatform,
  uDemoInit;
{$R *.dfm}

procedure TfrmMain.FormCreate(Sender: TObject);
begin
  fFpsTimer := 0;
  CreateDemo(self, fGlScene, fCadencer, fViewer);
  
  fCamera := TGlCamera.CreateAsChild(fGlScene.Objects);
  with fCamera do
  begin
    Position.SetPoint(0, 0, 5);
    Direction.SetVector(0, 0, -1);
    Up.SetVector(0, 1, 0);
    CameraStyle := csOrthogonal;
    SceneScale := 0.1;
  end;

  fMainDummy := TGLDummyCube.CreateAsChild(fGlScene.Objects);
  fMainDummy.ObjectsSorting := osNone;

  fViewer.Camera := fCamera;
  fCadencer.OnProgress := OnCadencerProgress;

  fMatLib := TGlMaterialLibrary.Create(self);

  InitMaterials;
  InitFontAndSprites;
  InitTweener;
end;

procedure TfrmMain.FormDestroy(Sender: TObject);
begin
  FreeAndNil(fTweener);
end;

procedure TfrmMain.FormActivate(Sender: TObject);
begin
  fCadencer.Enabled := true;
end;

Function TfrmMain.AddItem(aMaterial: String; aText: String; aPosX, aPosY, aWidthArea: Single; aBottomText: String): TItem;
begin
  result := TItem.Create;
  with result do
  begin
    fPosition := VectorMake(80 + aPosX * 70, aPosY, 0);
    
    fTextHud := TGlHudText.CreateAsChild(fMainDummy);
    with fTextHud do
    begin
      BitmapFont := fWinFont;
      ModulateColor.SetColor(0, 0, 0.3, 0.7);
      Alignment := taCenter;
      Text := aText;
      Position.SetPoint(fPosition[0], fPosition[1] - 10, 0);
    end;

    fMainHud := TGlHudSprite.CreateAsChild(fMainDummy);
    with fMainHud do
    begin
      Material.MaterialLibrary := fMatLib;
      Material.LibMaterialName := aMaterial;
      with Material.GetActualPrimaryTexture.Image do
        SetSize(Width, Height);
      Position.SetPoint(fPosition);
    end;

    fBottomText := aBottomText;
    fWidthArea := aWidthArea;
    fY := aPosY;
  end;
  fMenuItems.Add(result);
end;

Function TfrmMain.GetItem(aIndex: integer): TItem;
begin
  result := fMenuItems.Items[aIndex];
end;

Procedure TfrmMain.InitFontAndSprites;
begin
  fWinFont := TGLWindowsBitmapFont.Create(self);
  fWinFont.Font.Name := 'Arial';

  fBack := TGlHudSprite.CreateAsChild(fMainDummy);
  with fBack do
  begin
    Material.LibMaterialName := 'back';
    Material.MaterialLibrary := fMatLib;
    Width := Material.GetActualPrimaryTexture.Image.Width;
    Height := Material.GetActualPrimaryTexture.Image.Height;
    Position.SetPoint(Width / 2, Height / 2, 0);
  end;

  fMenuItems := TList.Create;

  fHudText := TGLHUDText.CreateAsChild(fMainDummy);
  with fHudText do
  begin
    BitmapFont := fWinFont;
    Text := 'Lampogolovii presents ''MenuItems Demo''';
    ModulateColor.SetColor(0, 0, 0.3, 0.7);
    Position.SetPoint(5, 2, 0);
    Alignment := taLeftJustify;
  end;

  fTextBar := TGlHudSprite.CreateAsChild(fMainDummy);
  with fTextBar do
  begin
    Material.LibMaterialName := 'textbar';
    Material.MaterialLibrary := fMatLib;
    Width := Material.GetActualPrimaryTexture.Image.Width;
    Height := Material.GetActualPrimaryTexture.Image.Height;
    Position.SetPoint(-400, 190, 0);
    fTextBarX := Position.X;
  end;

  fMenuText := TGLHUDText.CreateAsChild(fMainDummy);
  with fMenuText do
  begin
    BitmapFont := fWinFont;
    Text := 'Menu Text';
    ModulateColor.SetColor(0, 0, 0.3, 0.7);
    Position.SetPoint(-400, 190, 0);
    Alignment := taLeftJustify;
    Layout := tlCenter;
  end;

  fBottomText := TGlHudText.CreateAsChild(fMainDummy);
  with fBottomText do
  begin
    BitmapFont := fWinFont;
    Text := 'Simplicity in using...';
    ModulateColor.SetColor(0, 0, 0.3, 0.7);
    Position.SetPoint(-400, 220, 0);
    Alignment := taLeftJustify;
    Layout := tlTop;
    fBottomTextX := -400;
  end;
  
  AddItem('compass', 'Compass', 0, 80, 1, 'You could use this template for free!');
  AddItem('mail', 'Mail', 1, 80, 1, 'Is it hard to create animated menu?!');
  AddItem('notes', 'Notes', 2, 80, 1, 'Tween + GlScene = cool design in games...');
  AddItem('store', 'Options', 3, 80, 1, 'Add into your GUI some funny elements!');
  AddItem('video', 'Video', 4, 80, 1, 'Simple in using...');
  AddItem('messages', 'Messages', 5, 80, 1, 'Read more at lampogolovii.blogspot.com');
end;

Procedure TfrmMain.InitMaterials;
begin
  AddMaterials(fMatLib, str_ImagesFolder + '\MenuItems\', ['compass.png', 'mail.png', 'notes2.png', 'app store2.png', 'video.png', 'messages2.png'], MatNames);
  AddMaterial(fMatLib,  str_ImagesFolder + '\MenuItems\back_1.png', 'back');
  AddMaterial(fMatLib,  str_ImagesFolder + '\MenuItems\text_bar.png', 'textbar');
end;

Procedure TfrmMain.InitTweener;
begin
  MousePressed := false;
  fTweener := TTweener.Create;
end;

Procedure TfrmMain.SetPositions;
var
  i: integer;
begin
  for i := 0 to fMenuItems.Count - 1 do
    with GetItem(i) do
      fMainHud.Position.Y := Round(fY);
end;

Function TfrmMain.UpdateSelection(x, y: Integer): integer;
var
  i: integer;
begin
  result := -1;
  for i := 0 to fMenuItems.Count - 1 do
    with GetItem(i), GetItem(i).fMainHud do
      if (x > Position.X - Width/2 * fWidthArea)  and (x < Position.X + Width/2 * fWidthArea)
      and(y > Position.Y - fPosition[1] - Height) and (y < fPosition[1] + Height)then
      begin
        result := i;
        if not fSelected then
        begin
          fTweener.DeletePSingle(@fY);
          fTweener.AddTweenPSingle(@fY, ts_ExpoEaseIn, fY, fPosition[1] + 45, 1, 0);
        end;
        fSelected := true;
      end
      else
      begin
        if fSelected then
        begin
          fTweener.DeletePSingle(@fY);
          fTweener.AddTweenPSingle(@fY, ts_ElasticEaseOut, fY, fPosition[1], 2.5, 0);
        end;
        fSelected := false;  
      end;  
end;

Procedure TfrmMain.OnCadencerProgress(Sender : TObject; const deltaTime, newTime : Double);
var
  MPos: TPoint;
  Selected: Integer;
begin
  fTweener.Update(DeltaTime);

  GetCursorPos(Mpos);
  MPos := fViewer.ScreenToClient(MPos);

  SetPositions();
  Selected := UpdateSelection(MPos.X, MPos.y);
  fTextBar.Position.X := fTextBarX;
  fMenuText.Position.X := 530 - fTextBarX;
  fBottomText.Position.X := fBottomTextX;
  if IsKeyDown(vk_LButton) and not MousePressed and (Selected <> -1)then
  begin
    fMenuText.Text := GetItem(Selected).fTextHud.Text;
    fBottomText.Text := GetItem(Selected).fBottomText;

    fTweener.DeletePSingle(@fTextBarX);
    fTweener.AddTweenPSingle(@fTextBarX, ts_ExpoEaseIn, -500, 250, 1.5, 0);

    fTweener.DeletePSingle(@fBottomTextX);
    fTweener.AddTweenPSingle(@fBottomTextX, ts_ExpoEaseIn, -400, 80, 1.5, 0.4);
  end;

  MousePressed := IsKeyDown(vk_LButton);
end;

end.
